package com.service.scheduler.job;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

import com.service.bean.company.Company;
import com.service.bean.device.Vehicle;
import com.service.bean.other.OfflineData;
import com.service.bean.other.VariableData;
import com.service.cache.CacheManager;
import com.service.db.DbManager;
import com.service.other.Logger;
import com.service.other.ServerConfig;

/**
 * 离线检查任务
 * @author lj
 *
 */
public class OfflineJob implements Job {

	public OfflineJob() {
		
	}
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		JobKey jk = context.getJobDetail().getKey();
		String jobName = jk.getName();
		String jobGroup = jk.getGroup();
		Logger.println("启动任务 [" + jobGroup + "].[" + jobName + "]");
		// 任务启动时间(整点执行, 每15分钟执行一次, 当天最后一条为 23:59:59)
		// 使用该时间便于存储过程执行
		Date date = new Date(context.getFireTime().getTime() - 1000L);
		// 用于存储待插入到数据库的离线数据
		Map<Company, LinkedBlockingQueue<OfflineData>> dataMap = 
				new HashMap<Company, LinkedBlockingQueue<OfflineData>>();
		
		VariableData variable = null;
		int configTime = ServerConfig.instance().offLineTime;
		for (Vehicle vehicle : CacheManager.instance().vehicleMap.values()) {
			if (null == vehicle.lastGps)
				continue;
			variable = CacheManager.instance().getVariable(vehicle.device.deviceNo);
			long time = (date.getTime() - vehicle.lastGps.gpsTime.getTime()) / 1000L;
			if (time >= configTime * 60L) {
				// 超过报警阀值
				if (null == variable.offlineTime) {
					// 第一次报警
					variable.offlineTime = date;
					// 数据库中新增一条记录
					OfflineData data = createOfflineData(vehicle, date, 0);
					getOfflineDataSaveQueue(dataMap, vehicle.company).offer(data);
				} else {
					long t = (date.getTime() - variable.offlineTime.getTime()) / 1000L;
					if (t >= configTime * 60L) {
						// 持续离线时间超过阀值
						boolean flag = isSameDay(date, variable.offlineTime);
						if (flag) {
							// 上一次离线时间跟当前离线时间是同一天, 更新数据库
							OfflineData data = createOfflineData(vehicle, date, 1);
							getOfflineDataSaveQueue(dataMap, vehicle.company).offer(data);
						} else {
							// 上一次离线时间与今天不是同一天, 新增一条记录
							OfflineData data = createOfflineData(vehicle, date, 0);
							getOfflineDataSaveQueue(dataMap, vehicle.company).offer(data);
						}
						variable.offlineTime = date;
					}
				}
			}
		}
		if (null != dataMap && 0 != dataMap.size())
			DbManager.instance().dbo.batchSaveOfflineData(dataMap);
		Logger.println("任务执行完毕，下次启动时间：" + context.getNextFireTime());
	}

	private boolean isSameDay(Date d1, Date d2) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		if (sdf.format(d1).equals(sdf.format(d2))) {
			return true;
		}
		return false;
	}
	
	private OfflineData createOfflineData(Vehicle vehicle, Date offlineTime, int isInsert) {
		OfflineData data = new OfflineData();
		data.equipmentId = vehicle.equipmentId;
		data.lastOnlineTime = vehicle.lastGps.gpsTime;
		data.offlineTime = offlineTime;
		data.isInsert = isInsert;
		return data;
	}
	
	private LinkedBlockingQueue<OfflineData> getOfflineDataSaveQueue(
			Map<Company, LinkedBlockingQueue<OfflineData>> dataMap, Company company) {
		if (!dataMap.containsKey(company)) 
			dataMap.put(company, new LinkedBlockingQueue<OfflineData>());
		return dataMap.get(company);
	}
	
}
